package com.heima.article.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.cache.CacheService;
import com.heima.common.constants.ArticleConstants;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author itheima
 * @since 2022-07-29
 */
@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    private ApArticleMapper apArticleMapper;

    @Autowired
    private CacheService cacheService;

    @Override
    public void computeHotArticle() {
        // 1. 查五天内发布的文章
        LocalDateTime last5Day = LocalDateTime.now().minusDays(5);
        // publish_time
        List<ApArticle> list = apArticleMapper.findArticleByLast5days(last5Day);
        if (CollectionUtil.isEmpty(list)) {
            log.info("近五天没有新的文章");
            return;
        }

        // 2. 计算文章热度
        List<HotArticleVo> allList = compute(list);

        // 3. 分组（频道）
        List<List<HotArticleVo>> lists = CollectionUtil.groupByField(allList, "channelId");
        if (CollectionUtil.isEmpty(lists)) {
            log.warn("分组数据为空");
            return;
        }

        // 4. 根据分组进行排序
        // 5. 写入缓存
        for (List<HotArticleVo> hotArticleVos : lists) {
            if (CollectionUtil.isEmpty(hotArticleVos)) {
                continue;
            }

            // 参数一：我要缓存的集合数据
            // 参数二：我要缓存的数据对应的频道id
            Integer channelId = hotArticleVos.get(0).getChannelId();
            sortAndCaching(hotArticleVos, channelId.toString());
        }

        // 6. 推荐频道计算和处理
        sortAndCaching(allList, ArticleConstants.DEFAULT_TAG);

    }

    private void sortAndCaching(List<HotArticleVo> voList, String channelId) {
        // 1. 排序 stream.sort
        voList = voList.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).collect(Collectors.toList());

        // 2. 截取30条
        if (voList.size() > 30) {
            voList = voList.subList(0, 30);
        }

        // 3. 写入缓存
        cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + channelId, JSON.toJSONString(voList));
    }


    private List<HotArticleVo> compute(List<ApArticle> list) {
        if (CollectionUtil.isEmpty(list)) {
            return new ArrayList<>();
        }

        List<HotArticleVo> resultList = new ArrayList<>();
        for (ApArticle apArticle : list) {
            if (apArticle == null) {
                continue;
            }

            Integer score = 0;

            // 阅读 +1
            Integer views = apArticle.getViews();

            // 点赞 +3
            Integer likes = apArticle.getLikes();

            // 评论 +5
            Integer comment = apArticle.getComment();

            // 收藏 +8
            Integer collection = apArticle.getCollection();

            if (views != null) {
                score += views;
            }

            if (likes != null) {
                score += likes * 3;
            }

            if (comment != null) {
                score += comment * 5;
            }

            if (collection != null) {
                score += collection * 8;
            }

            HotArticleVo vo = new HotArticleVo();
            vo.setScore(score);
            BeanUtils.copyProperties(apArticle, vo);
            resultList.add(vo);
        }

        return resultList;
    }
}
